<?php

namespace App\Http\Controllers\Admin;

use Illuminate\Http\Request;
use App\Models\Machine;
use App\Models\Mainborad;
use App\Models\MachineConfig;
use Illuminate\Support\Facades\DB;
use App\Models\FreightWay;
use App\Models\FreightWayDemoData;
use App\Models\Goods;
use App\Models\Broker;
use App\Models\Merchant;
use App\Events\MachineState;
use App\Events\MachineGoodsEvent;
use App\Services\Mqtt\Publishs;
use App\Services\Qrcode\SimpleQrcode;
use Zipper;
use Illuminate\Support\Facades\Storage;
use App\Http\Requests\Admin\MachineRequest;
use App\Models\Auth;
use App\Models\MachineManager;
use App\Models\Orders;
use App\Models\Operator;
use App\Models\MachineAbImages;
use App\Services\Traits\UploadImageTrait;


class MachineController extends Controller
{

    use UploadImageTrait;

    protected $path = 'upload/machine/abimages/';

    protected $check_field = 'abImage';
        /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request, Machine $machine, Merchant $merchant, Broker $broker, Mainborad $mainborad, Operator $operator)
    {
        $user = auth('admin')->user();
        if($user->type != 1){
            $machine = $machine->whereHas('machine_managers', function($query) use($user){
                $query->where('manager_id' , $user->id);
            });
        }
        $machines = $machine->with('mainborad')->filter($request->all())->orderBy('id','desc')->paginate(config('api.page.limit'));
        $query['imei'] = $request->imei ?? '';
        $query['broker'] = $request->broker ?? '';
        $query['merchant'] = $request->merchant ?? '';
        $query['state'] = $request->state ?? '';
        $query['expire_time'] = $request->expire_time ?? '';
        $query['online'] = $request->online ?? '';
        $query['operator'] = $request->operator ?? '';
        $query['id'] = $request->id ?? '';
        $query['mainborad'] = $request->mainborad ?? '';
        return view('admins.machine.index', compact('machines','query'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create(Mainborad $mainborad)
    {
        $mainborads = $mainborad->all();
        return view('admins.machine.add', compact('mainborads'));
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(MachineRequest $request)
    {
        $data = $request->all();
        $imeis = explode("\n",trim($data['imei']));
        foreach ($imeis as $imei) {
            $result = DB::transaction(function()use($imei, $data){
                $data['imei'] = trim($imei);
                $machine = new Machine();
                $machine_info = $machine->query()->create($data);
                if(!$machine_info){
                    throw new Exception("设备添加失败");                
                }
                foreach ($data['config'] as $key => $value) {
                    $config[] = new MachineConfig($value);
                }
                $machine_info->config()->saveMany($config);
                foreach ($data['freight_way'] as $key1 => $value1) {
                    $freightWayData[] = new FreightWay([
                        'capacity' => $value1['capacity'],
                        'state' => $value1['state'],
                        'type' => $value1['type'],
                        'No' => $value1['No'],
                    ]);
                }
                $machine_info->freight_way()->saveMany($freightWayData); 
                event(new MachineState($machine_info)); 
                return true;
            }); 
            if(!$result){
                return json_encode(['code' => 200, 'msg' => 'error']);
            }
        }             
        return json_encode(['code' => 200, 'msg' => 'success']);  
        
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit(Mainborad $mainborad, Machine $machine)
    {
        $mainborads = $mainborad->all();
        return view('admins.machine.edit', compact('machine', 'mainborads'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Machine $machine)
    {
        $result = $machine->update($request->all());
        if(!$result){
            return json_encode(['code' => 200, 'msg' => 'error']);
        }
        return json_encode(['code' => 200, 'msg' => 'success']);
    }

    public function show(Request $request,Machine $machine,  SimpleQrcode $qrcode)
    {
        $qr = $qrcode->webStore(get_web_host($machine->id)); //;
        $id = $machine->id;
        return view('admins.machine.show', compact('id','qr'));
    }
    //下载二维码
    public function downloadQrcode(Request $request, SimpleQrcode $qrcode, Machine $machine)
    {
        $machine = $machine->where('id',$request->machine_id)->first();
        return response()->stream(function () use ($machine, $qrcode) {
            echo $qrcode->webStore(get_web_host($machine->id));
        }, 200, [
            "Content-type"=>"image/png",
            "Content-Disposition"=>"attachment; filename=machine-{$machine->id}-qrcode.png"
        ]);
    }

    //设备详情数据
    public function info(Request $request, Machine $machine)
    {        
        $machine = $machine->with('config','mainborad', 'freight_way_demo')->where('id', $request->machine_id)->first();
        return json_encode(['code' => 200, 'msg' => 'success', 'data' => $machine]);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    // public function destroy(Machine $machine)
    // {
    //     $machine->delete();
    //     return redirect()->route('admin.machines.index')->with('success', '添加成功');
    // }
    public function delete(Request $request, Machine $machine)
    {
        $machine = $machine->with('machine_managers')->find($request->id);
        if($machine->machine_managers->isNotEmpty()){
            return json_encode(['code' => 400, 'message' => '该设备已经绑定用户,请移除后删除']);
        }
        $machine->delete();
        return json_encode(['code' => 200, 'message' => '删除成功']);
    }
    //参数配置
    public function config(Machine $machine, MachineConfig $config)
    {
        $machine_id = $machine->id;
        $config = $config->where('machine_id',$machine->id)->get();
        $config = optional($config)->toArray();
        return view('admins.machine.config',compact('config', 'machine_id'));
    }
    //更新设备参数
    public function configUpdate(Request $request, MachineConfig $config)
    {
        $configData = $request->config;
        foreach ($configData as $key => $value) {
            $config->where('id',$value['id'])->update($value);
        }
        //发送mqtt设置信息
        $config->mqttPublish($request->machine_id);
        return json_encode(['code' => 200, 'msg' => 'success']);
    }

    /**
     * 货道信息
     */
    public function freight(Request $request, FreightWay $freight)
    {
        $freights = $freight->with('goods')->filter($request->all())->where('machine_id', $request->machine_id)->get();
        return json_encode(['code' => 200, 'msg' => 'success', 'data' => $freights]);
    }

    //商品列表
    public function goodsLists(Request $request, Goods $goods, Machine $machine)
    {
        $machine = $machine->find($request->machine_id);
        $user_id = optional($machine->merchant)->id;
        $result = $goods->with('goodsType')
            ->filter($request->all())
            ->where(['state' => 1, 'merchant_id' => $user_id])
            ->orderBy('created_at', 'desc')
            ->paginate(config('api.page.limit'));
        return json_encode(['code' => 200, 'msg' => 'success', 'data' => $result]);
    }

    //一键补货
    public function freightAddStock(Request $request, FreightWay $freight)
    {
        $freights = $freight->where('machine_id', $request->id)->where('state', '<>', 0)->get();
        foreach ($freights as $key => $value) {
            if($value->stock < $value->capacity){
                $value->stock = $value->capacity;
                $value = $value->save();
            }            
        }
        return json_encode(['code' => 200, 'msg' => 'success']);
    }

    //通过设备更新货道
    public function freightUpdate(Request $request, FreightWay $freight)
    {
        $freights = $freight->where('machine_id', $request->machine_id)->get();
        $copyFreights = $freight->where('machine_id', $request->copy_id)->get();
        foreach ($freights as $key => $value) {
            $copyFreight = $copyFreights->firstWhere('No',$value->No);
            if($copyFreight){
                $value->goods_id = $copyFreight->goods_id;
                $value->capacity = $copyFreight->capacity;
                $value->stock = $copyFreight->stock;
                $value->stock_warning = $copyFreight->stock_warning;
                $value->state = $copyFreight->state;
                $value->type = $copyFreight->type;
                $value->price = $copyFreight->price;
                $value->save();
            }
        }
        return json_encode(['code' => 200, 'msg' => 'success']);
    }
    //通过模板更新货道
    public function freightDemoUpdate(Request $request,FreightWay $freight, FreightWayDemoData $freightDemo)
    {
        $copyFreights = $freightDemo->where('freight_way_demo_id', $request->freight_demo_id)->get();        
        foreach ($copyFreights as $key => $value) {
            $freights = $freight->where(['machine_id' => $request->machine_id, 'No' => $value->No])->first();
            if($freights){
                $freights->capacity = $value->capacity;
                $freights->state = $value->state;
                $freights->type = $value->type;
                $freights->save();
            }else{
                $freight->create([
                                    'machine_id' => $request->machine_id, 
                                    'goods_id' => 0, 
                                    'capacity' => $value->capacity, 
                                    'stock' => 1,
                                    'stock_warning' => 1,
                                    'state' => $value->state,
                                    'price' => 0.00,
                                    'No' => $value->No,
                                    'type' => $value->type,
                                    'buying_price' => 0.00]);
            }
            
        }
        return json_encode(['code' => 200, 'msg' => 'success']);
    }
    //开锁测试
    public function freightOpen(Request $request, FreightWay $freight)
    {
        $freight = $freight->with('machine')->where('id',$request->freight_id)->first();
        if(strtotime($freight->machine->expire_time) <= time()){
            return json_encode(['code' => 400, 'msg' => '该设备已经过期', 'data' => '']);
        }
        if($freight){
            // if($freight->state == 1){
                $open = [
                    'IMEI' => optional($freight->machine)->imei,
                    'Command' => machine_command('out'),
                    'Slot_Index' => $freight->No,
                    'Number' => 1,
                    'Order_Number' => (string)time(),
                    'Count' => 1,
                    'Type' => $freight->type,
                    'Time' => time(),
                ];
                $pub = new Publishs;
                $topic = mqtt_topic('out',optional($freight->machine)->imei);
                $res = $pub->publish($topic, json_encode($open), 'server_1_laravel5.8');
                return json_encode(['code' => 200, 'msg' => 'success', 'data' => $res]);
            // }else{
            //     return json_encode(['code' => 202, 'msg' => freight_state($freight->state), 'data' => '']);
            // }
        }else{
            return json_encode(['code' => 400, 'msg' => '设备不存在', 'data' => '']);
        }
    }

    //测试设备是否存在
    public function checkUnique(Request $request, Machine $machine)
    {
        $imei = $request->imei;
        $imeis = explode("\n",trim($imei));
        foreach ($imeis as $key => $value) {
            $machine = $machine->where('imei', $value)->first();
            if($machine){
                return json_encode(['code' => 200, 'msg' => '该设备已经存在', 'data' => $value]);
            }
        }
        return json_encode(['code' => 400, 'msg' => 'success', 'data' => '']);
    }

    //获取无分页设备
    public function lists(Request $request, Machine $machine, Merchant $merchant)
    {
        $machines = [];
        if($request->merchant_id){
            $merchant = $merchant->with('machine')->find($request->merchant_id);
            $machines = $merchant->machine;
        }
        return response()->json(['code' => 200, 'msg' => 'success', 'data' => $machines]);        
    }

    //生成货道二维码
    public function freightQrcode(Request $request, SimpleQrcode $qrcode, Machine $machine)
    {
        $machine = $machine->with('freight_way')->where('id',$request->machine_id)->first();
        $path = 'app/public/machines/machine_'. $machine->imei .'/freight_qrcode/';        
        if(!file_exists(storage_path($path))){
            mkdir(storage_path($path), 0755, true);
        }
        $zipname = $path.'machine_'.$machine->imei.'_freight.zip';
        Storage::delete(storage_path($zipname));
        $zipper = Zipper::make(storage_path($zipname))->folder('machine_'.$machine->imei.'_freight');
        foreach ($machine->freight_way as $key => $value) {
            $fillname = 'freight_'.$value->No.'.png';
            if(!file_exists(storage_path($path.$fillname))){
                $qrcode->webStore(get_web_host($machine->id, $value->No),storage_path($path.$fillname));
            }
            // 将文件加入 zip 包
            $zipper->add(storage_path($path.$fillname));
        }   
        // 关闭zip，一定要调用
        $zipper->close();
        // 返回下载响应，下载完成后删除文件
        return json_encode(['code' => 200, 'msg' => 'success', 'data' => env('APP_URL').Storage::url('public/machines/machine_'. $machine->imei .'/freight_qrcode/machine_'.$machine->imei.'_freight.zip')]);
    }  
    //批量修改货道
    public function freightEdit(Request $request, FreightWay $freight)
    {   
        $data = $request->all();
        $update_data = [];
        if($data['edit_capacity']){
            $update_data['capacity'] = $data['capacity'];
        }
        if($data['edit_type']){
            $update_data['type'] = $data['type'];
        }
        if($data['edit_state']){
            $update_data['state'] = $data['state'];
        }
        if($data['edit_stock']){
            $update_data['stock'] = $data['stock'];
        }
        if($data['edit_stock_warning']){
            $update_data['stock_warning'] = $data['stock_warning'];
        }
        if($data['edit_price']){
            $update_data['price'] = $data['price'];
        }
        $fail = [];
        $success = 0;
        if(count($update_data)){
            if(!empty($data['start']) && !empty($data['end'])){
                for ($i=$data['start']; $i <= $data['end']; $i++) { 
                    $res = $freight->where(['machine_id' => $data['machine_id'], 'No' => $i])->update($update_data);
                    if(!$res){
                        $fail[] = $i;
                    }else{
                        $success++;
                    }
                }
            }elseif(!empty($data['singles'])){
                $singles = explode(',', $data['singles']);
                foreach ($singles as $key => $value) {
                    $res = $freight->where(['machine_id' => $data['machine_id'], 'No' => $value])->update($update_data);
                    if(!$res){
                        $fail[] = $i;
                    }else{
                        $success++;
                    }
                }
            }
        }        
        return json_encode(['code' => 200, 'msg' =>['success' => $success, 'fail' => count($fail), 'failNo' => implode(',',$fail)]]);
    }
    //绑定商品
    public function freightBindGoods(Request $request, FreightWay $freight)
    {
        $freight_info = $freight->where('id', $request->freight_id)->first();
        $freight_info->goods_id = $request->goods_id;
        $freight_info->save();
        return json_encode(['code' => 200, 'msg' => 'success']);
    }
    //更新货道数据
    public function freightUpdateData(Request $request, FreightWay $freight)
    {
        $freight = $freight->find($request->id);
        $freight->capacity = $request->capacity;
        $freight->stock = $request->stock;
        $freight->stock_warning = $request->stock_warning;
        $freight->price = $request->price;
        $freight->type = $request->type;
        $freight->state = $request->state;
        $freight->buying_price = $request->buying_price;
        $freight->save();
        return json_encode(['code' => 200, 'msg' => 'success']);
    }

    //绑定设备
    public function bindMachines(Request $request, Auth $auth, Machine $machine, MachineManager $machine_manager)
    {    
        $errorImei = [];
        $manager = $auth->find($request->manager_id);
        $managers = $auth->getPrentAll($manager);
        $manager_ids = collect($managers)->prepend($manager);
        $imeis = explode("\n",trim($request->imei));
        foreach ($imeis as $key => $value) {
            $machine = $machine->where('imei', $value)->first();
            if($machine){
                //$binds = $machine_manager->where('machine_id', $machine->id)->whereNotIn('manager_id',$manager_ids->pluck('id')->toArray())->get();
                // if($binds->isEmpty()){
                    foreach ($manager_ids as $item) {
                        $data[$item->id] = ['type' => $item->type, 'percentage' => '0.01'];
                    }
                    $machine->manager()->sync($data);
                // }else{
                //     $errorImei[] = ['imei' => $value, 'error' => '该设备已经被绑定'];
                // }
            }else{
                $errorImei[] = ['imei' => $value, 'error' => '该设备不存在'];
            }
            
        }
        return json_encode(['code' => 200, 'msg' => 'success', 'error' => $errorImei]);
    }
    //经销商列表
    public function getChildrenAll(Request $request, Auth $manager)
    {
        $user = auth('admin')->user();
        if($user->type == 1){
            $managers = $manager->where('type',$request->type)->get();
        }
        if($user->type == 2){
            $broker_ids = [];
            array_push($broker_ids,$user->id);
            $brokers = $manager->where('type', 2)->where('parent_id', $user->id)->select('id')->get();
            if($brokers->isNotEmpty()){
                $ids = $brokers->pluck('id');
                $broker_ids = array_merge($broker_ids, $ids->toArray());
            }
            $managers = $manager->where('type',$request->type)->whereIn('parent_id',$broker_ids)->get();
        }
        if($user->type == 3){
            $managers = $manager->where('type',$request->type)->where('parent_id',$user->id)->get();
        }
        return json_encode(['code' => 200, 'msg' => 'success', 'data' => $managers]);
    }
     //修改绑定的商户
    public function changeMerchant(Request $request, Auth $auth, Machine $machine, FreightWay $freight)
    {
        $machine = $machine->find($request->machine_id);
        $machine->manager()->detach();
        if($request->merchant_id){            
            $manager = $auth->find($request->merchant_id);
            $managers = $auth->getPrentAll($manager);
            $manager_ids = collect($managers)->prepend($manager);
            foreach ($manager_ids as $item) {
                $data[$item->id] = ['type' => $item->type, 'percentage' => '0.01'];
            }
            $machine->manager()->sync($data);
            //清除商品
            $freight = $freight->where('machine_id',$request->machine_id)->where('goods_id', '<>', 0)->get();
            event(new MachineGoodsEvent($freight));                    
        }
        return json_encode(['code' => 200, 'msg' => 'success']);    
    }
    //一键出货
    public function outAll(Request $request, Machine $machine)
    {
        $machine_info = $machine->with('freight_way')->find($request->machine_id);
        $freights = optional($machine_info->freight_way)->where('state', '<>', 0);
        if($freights->isNotEmpty()){
            foreach ($freights as $key => $value) {
                $freight_No[] = [$value->No, $value->type];
            } 
            $open = [
                'IMEI' => $machine_info->imei,
                'Command' => machine_command('out_all'),
                'Slot' => $freight_No,
            ];
            $pub = new Publishs;
            $topic = mqtt_topic('out_all',$machine_info->imei);
            $res = $pub->publish($topic, json_encode($open), 'server_1_laravel5.8');
            return json_encode(['code' => 200, 'msg' => 'success']);
        }
        
    }
    //该设备的所有订单
    public function orders(Request $request, Orders $order, Machine $machine)
    {
        $machine = $machine->find($request->id);
        $data = $order->with('goods')->whereHas('order_merchant', function($query) use ($machine){
            $query->where('merchant_id',optional($machine->merchant)->id);
        })->filter($request->all())->where('couter_id',$request->id)->orderBy('id','desc')->paginate(config('api.page.limit'));

        $total_price = $order->whereHas('order_merchant', function($query) use ($machine){
            $query->where('merchant_id',optional($machine->merchant)->id);
        })->filter($request->all())
        ->where('couter_id', $request->id)
        ->select('*',DB::raw("sum(order_total_price) as order_total_price_num"))
        ->groupBy('payment')
        ->orderBy('id','desc')
        ->get();
        return json_encode(['code' => 200, 'msg' => 'success', 'data' => $data, 'total_price' => $total_price]);
    }
    //初始化设备
    public function reset(Request $request, Machine $machine, Orders $order, FreightWay $freight)
    {
        $machine = $machine->find($request->id);
        $machine->manager()->detach();
        $freight_data = [
            'goods_id' => 0,
            'capacity' => 0,
            'stock' => 0,
            'stock_warning' => 0,
            'price' => 0.00,
            'type' => 1,
        ];
        $freight->where('machine_id', $request->id)->update($freight_data);
        $order->where('couter_id', $request->id)->delete();
        return json_encode(['code' => 200, 'msg' => 'success']);
    }
    //删除订单
    public function deleteOrder(Request $request, Orders $order)
    {
        $machine_id = $request->machine_id;
        $res = $order->where('couter_id', $machine_id)->delete();
        if($res){
            return json_encode(['code' => 200, 'msg' => 'success']);
        }else{
            return json_encode(['code' => 400, 'msg' => 'error']);
        }
    }
    //重启设备
    public function restart(Request $request, Machine $machine)
    {
        $machine = $machine->find($request->machine_id);
        if($machine){
            $pub = new Publishs;
            $topic = mqtt_topic('restart',$machine->imei);
            $res = $pub->publish($topic, json_encode(['IMEI' => $machine->imei, 'Command' => 102]), 'server_1_laravel5.8');
            if($res){
                return json_encode(['code' => 200, 'msg' => '重启指令发送成功']);
            }
        }
        return json_encode(['code' => 400, 'msg' => '该设备不存在']);
    }
    //一键清除货道故障
    public function clearFreightError(Request $request, FreightWay $freight)
    {
        $res = $freight->where('machine_id', $request->machine_id)->where('state', '>', '1')->update([
            'state' => 1
        ]);
        if($res){
            return json_encode(['code' => 200, 'msg' => '更新成功']);
        }else{
            return json_encode(['code' => 400, 'msg' => '更新失败']);
        }
    }
    //设备参数设置
    public function paramsSettings(Request $request, Machine $machine)
    {
        $machine = $machine->find($request->id);
        $machine->nickname = $request->nickname;
        $machine->title = $request->title;
        $res = $machine->save();
        if($res){
            return json_encode(['code' => 200, 'msg' => '设置成功']);
        }else{
            return json_encode(['code' => 400, 'msg' => '设置失败']);
        }
    }

    //广告图片列表
    public function abImageList(Request $request,MachineAbImages $images)
    {
        $images = $images->where(['machine_id' => $request->id])->orderBy('order','desc')->paginate(config('api.page.limit'));
        return json_encode(['code' => 200, 'msg' => 'success', 'data' => $images]);
    }
    //添加设备广告图片
    public function addAbImage(Request $request, MachineAbImages $images)
    {
        $result = $images->create($request->all());
        return json_encode(['code' => 200, 'msg' => 'success']);
    }
    //删除设备广告图片
    public function delAbImage(Request $request, MachineAbImages $images)
    {
        $images->where('id',$request->id)->delete();
        return json_encode(['code' => 200, 'msg' => 'success']);
    }
}
